//==================================================================
//  Copyright (C) 2006-2007  Davide Pasca
//
//  This library is free software; you can redistribute it and/or
//  modify it under the terms of the GNU Lesser General Public
//  License as published by the Free Software Foundation; either
//  version 2.1 of the License, or (at your option) any later version.
//
//  This library is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
//  Lesser General Public License for more details.
//
//  You should have received a copy of the GNU Lesser General Public
//  License along with this library; if not, write to the Free Software
//  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
//==================================================================
/// @file	psys.h
///
/// Basic OS services.
///
//==================================================================

#ifndef PSYS_H
#define PSYS_H

//==================================================================
#include <string.h>
#include <tchar.h>

//==================================================================
//== Platform detection
//==================================================================
#ifdef _MSC_VER
	#pragma warning(disable : 4244)
	#pragma warning(disable : 4305)
	#pragma warning(disable : 4018)
	#pragma warning(disable : 4761)
	#pragma warning(disable : 4554)
	#pragma warning(disable : 4267)	// yet another fagful warning to avoid ! -- conversion from 'size_t' to 'int', possible loss of data

	#define PFORCEINLINE	__forceinline
#endif

#ifdef __MWERKS__
	#pragma warn_unusedarg		off
	#pragma warn_possunwant		off
	#pragma warn_emptydecl		off
	#pragma warn_implicitconv	off

	#define PFORCEINLINE	inline
#endif

//==================================================================
#include "psys_types.h"

//==================================================================
//== Good old macros
//==================================================================
#define NOT(_X_)			(!(_X_))
#define PABS(_X_)			((_X_)<0?-(_X_):(_X_))
#define PCLAMP(A,MI,MA)		{if ((A)<(MI)) (A) = (MI); else if ((A)>(MA)) (A)=(MA);}
#define PMIN(_A_,_B_)		((_A_) < (_B_) ? (_A_) : (_B_))
#define PMAX(_A_,_B_)		((_A_) > (_B_) ? (_A_) : (_B_))
#define SAFE_FREE(_X_)		{if (_X_){ PSYS_FREE(_X_); (_X_)=0; } }
#define SAFE_DELETE(_X_)	{if ((_X_) != NULL){ delete (_X_); (_X_)=0; } }

//==================================================================
#define PSYS_MSG_PRINTF			PSYS::MsgPrintf

#ifdef _DEBUG
	#define PASSERT(_X_)			PSYS::Assert((bool)(_X_),_T(__FILE__),__LINE__)
	#define PASSERTMSG(_X_,_MSG_)	PSYS::AssertMsg((bool)(_X_),(_MSG_),_T(__FILE__),__LINE__)
	#define PASSERT_RET(_X_)		(PSYS::Assert((bool)(_X_),_T(__FILE__),__LINE__))
	#define PDEBUG_PRINTF			PSYS::DebugPrintF
#else
	#define PASSERT(_X_)			
	#define PASSERTMSG(_X_,_MSG_)	
	#define PASSERT_RET(_X_)		(_X_)
	#define PDEBUG_PRINTF			{}
#endif

#define ERR_NULL(_X_)		(!PASSERT_RET( ((_X_) != NULL) ))
#define ERR_FALSE(_X_)		(!PASSERT_RET( ((_X_) != false) ))
#define ERR_ERROR(_X_)		(!PASSERT_RET( ((_X_) > PERROR) ))

#define PTRAP_FALSE(_X_)	( PASSERT_RET( (_X_) ) )
#define PTRAP_TRUE(_X_)		( !PASSERT_RET( !(_X_) ) )

#define PBADPATH(_X_)		(!PASSERT_RET(!(_X_)))

//==================================================================
namespace PSYS {

//==================================================================
//== BEGIN OF FUNCTIONS
//==================================================================
void		Initialize( const TCHAR *log_fnamep );
u_long64	TimerGetUL64();
double		TimerGetD();


//------------------------------------------------------------------
/** Reports on the failure of a boolean expression.

	@param   ok  		- Boolean value. 0 represents failure.
	@param   srcfnamep	- Name of the source code where the function
						  is located (typically defined as __FILE__).
	@param   line		- Line of code where the function is being
						  called from (typically defined as __LINE__).
	
	@note    This function is called by the macro PASSERT().
			 PASSERT() only takes the 'ok' value and automatically
			 utilizes __FILE__ for 'srcfnamep' and __LINE__ for 'line'.
*/
int Assert( int ok, const TCHAR *srcfnamep, int line );
int AssertMsg( int ok, const TCHAR *msgp, const TCHAR *srcfnamep, int line );

void DebugPrintF( const TCHAR *fmt, ... );
void MsgPrintf( const TCHAR *fnamep, int line, const TCHAR *fmtp, ... );

//==================================================================
PError GLErrorCheck( const TCHAR *srcfnamep, int line );

//==================================================================
//== FILE FUNCTIONS
//==================================================================
#if defined(_FILE_DEFINED) || defined(_MSL_STDIO_H)
	int	psys_fread( void *destp, size_t size, size_t count, FILE *fp );
	void psys_replace_fread( int (*user_defined_fread)( void *, size_t, size_t, FILE * ) );

	TCHAR *TFGets_UTF8( FILE *fp, TCHAR *desp, u_int des_max );
#endif

};

//==================================================================
#include "psys_memory.h"
#include "psys_container.h"
#include "psys_string.h"

#endif